﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace FrameworkCore.Attributes;

public sealed class SaveChangesAttribute<TContext> : ActionFilterAttribute where TContext : DbContext
{
    private readonly bool _saveChanges;

    public SaveChangesAttribute(bool saveChanges = true)
    {
        _saveChanges = saveChanges;
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var dbContext = (TContext)context.HttpContext.RequestServices.GetRequiredService(typeof(TContext));
        var transaction = dbContext.Database.BeginTransaction();

        try
        {
            var actionExecuted = await next();

            if (actionExecuted.Exception == null && _saveChanges)
            {
                await dbContext.SaveChangesAsync();
                transaction.Commit();
            }
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        finally
        {
            transaction.Dispose();
        }
    }
}
